/**
 * 
 */
package vwg.na.vwm.rh.motorsdk.modelo.procesos.daoimpl;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

import org.springframework.stereotype.Repository;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import vwg.na.vwm.rh.modulo.pad.MontosMensuales;
import vwg.na.vwm.rh.modulo.pad.util.ResultadoEmpleado;
import vwg.na.vwm.rh.motorsdk.commons.entidades.EstructuraEmpresa;
import vwg.na.vwm.rh.motorsdk.modelo.procesos.PadPlaneacionPersonalProceso;
import vwg.na.vwm.rh.motorsdk.modelo.procesos.dao.PadPlaneacionPersonalDAO;
import vwg.na.vwm.rh.motorsdk.modelo.procesos.entidadesgrales.PadCapturaEjercicio;
import vwg.na.vwm.rh.motorsdk.modelo.procesos.entidadesgrales.PadEstadoPlaneacionPersonal;
import vwg.na.vwm.rh.motorsdk.modelo.procesos.entidadesgrales.PadPPTipoMovimiento;
import vwg.na.vwm.rh.motorsdk.modelo.procesos.entidadesgrales.PadPlaneacionPersonalMovimiento;
import vwg.na.vwm.rh.rhmotor.modelo.dao.GenericDAO;

/**
 * @author Joel Ochoa [joel.ochoa@vw.com.mx]
 *
 */
@Repository
public class PadPlaneacionPersonalDAOImpl  extends GenericDAO< PadPlaneacionPersonalProceso> 
implements PadPlaneacionPersonalDAO {
	
	/* (non-Javadoc)
	 * @see vwg.na.vwm.rh.motorsdk.modelo.procesos.dao.PadPlaneacionPersonalDAO#getTipoMovimiento()
	 */
	@SuppressWarnings("unchecked")
	@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
	@Override
	public List<PadPPTipoMovimiento> getTiposMovimiento() {
		return getHibernateTemplate().find("FROM PadPPTipoMovimiento tipoMovimiento where tipoMovimiento.visible = '1'");}
	

	@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
	@Override
	public List<ResultadoEmpleado> findPersonal(String nombre, String paterno, String materno,
			String[] uos, String sociedad, String grado, String equidad, String evd) {
		
		StringBuilder query = new StringBuilder("select persona");
		query.append(" from EstructuraEmpresa persona where");
		query.append(" (persona.persona.nombre like :nombre and persona.persona.paterno like :paterno");
		query.append(" and persona.persona.materno like :materno");
		query.append(" and estructuraEmpresa.posicion.posicionGrado like :grado)");
		query.append(" and estructuraEmpresa.posicion.unidadOrganizativa.unidadOrganizativa in (:uos)");
		query.append(" and estructuraEmpresa.sociedad.sociedad = :sociedad");
		
		
		String[] paramNames = {"nombre", "paterno", "materno", "uos", "grado", "sociedad"};
		
		Object[] values = {nombre, paterno, materno, uos, grado, sociedad};
		
		@SuppressWarnings("unchecked")
		List<EstructuraEmpresa> resultadosBusqueda = getHibernateTemplate().findByNamedParam(query.toString(), paramNames, values);
		
		List<ResultadoEmpleado> resultadosPersonal = new ArrayList<ResultadoEmpleado>();
		
		for(EstructuraEmpresa persona : resultadosBusqueda){
			ResultadoEmpleado resultado = new ResultadoEmpleado();

			getHibernateTemplate().initialize(persona.getPersona());
			resultado.setPersona(persona.getPersona());
			resultado.setUnidadOrganizativa(persona.getPosicion().getUnidadOrganizativa());
			resultado.setGrado(persona.getPosicion().getPosicionGrado());
			resultado.setEquidad("N/A");
			resultado.setEvd("N/A");
			resultado.setSueldo(new BigDecimal(persona.getPersona().getRemuneracion().getSalarioMensual()));
			
			resultadosPersonal.add(resultado);
		}
		
		return resultadosPersonal;
	}

	@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
	@Override
	public PadPlaneacionPersonalProceso getPlaneacionPersonal(
			int definicionBudget) {
		StringBuilder query = new StringBuilder("select planeacion ");
		query.append(" from PadPlaneacionPersonalProceso planeacion where");
		query.append(" definicionBudget = :def");
		
		@SuppressWarnings("unchecked")
		List<PadPlaneacionPersonalProceso> results = 
				getHibernateTemplate().findByNamedParam(
						query.toString(), "def", definicionBudget);
		
		PadPlaneacionPersonalProceso planeacion = null;
		
		if(results.size() > 0){
			planeacion = results.get(0);
		}
		
		return planeacion;
	}

	@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
	@Override
	public PadEstadoPlaneacionPersonal getEstadoPlaneacionPersonal(int estado) {
		return getHibernateTemplate().get(PadEstadoPlaneacionPersonal.class, estado);
	}

	@Transactional(readOnly = true, propagation = Propagation.REQUIRED)
	@Override
	public PadCapturaEjercicio getCapturaEjercicio() {
		StringBuilder query = new StringBuilder("select capturaEjercicio ");
		query.append(" from PadCapturaEjercicio capturaEjercicio");
		
		@SuppressWarnings("unchecked")
		List<PadCapturaEjercicio> resultados = getHibernateTemplate().find(query.toString());
		
		PadCapturaEjercicio capturaEjercicio = null;
		
		if(resultados.size() > 0){
			capturaEjercicio = resultados.get(0);
		}
		
		return capturaEjercicio;
	}

	@Override
	public MontosMensuales getMontosMensualesMovimientosPadre(String uoPadre, String sociedad, int anio) {
		StringBuilder query = new StringBuilder("select movimiento ");
		query.append(" from PadPlaneacionPersonalMovimiento movimiento where");
		query.append(" (movimiento.tipoMovimiento = 1 or movimiento.tipoMovimiento = 2)");
		query.append(" and movimiento.estadoMovimiento <> 3 and");
		query.append(" movimiento.planeacionPersonal.padDefinicionBudget.unidadOrganizativa.unidadOrganizativa");
		query.append(" = :uo and");
		query.append(" movimiento.planeacionPersonal.padDefinicionBudget.sociedad.sociedad");
		query.append(" = :soc and");
		query.append(" movimiento.planeacionPersonal.padDefinicionBudget.anio");
		query.append(" = :anio");
		
		String[] paramNames = {"uo", "soc", "anio"};
		
		Object[] values = {uoPadre, sociedad, anio};
		
		@SuppressWarnings("unchecked")
		List<PadPlaneacionPersonalMovimiento> resultados = getHibernateTemplate().findByNamedParam(query.toString(), paramNames, values);
		
		MontosMensuales monto = getMontosMensuales(resultados);
		
		return monto;
	}
	
	private MontosMensuales getMontosMensuales(List<PadPlaneacionPersonalMovimiento> movimientos){
		
		BigDecimal[] montos = new BigDecimal[12];
		
		// Se inicializan en cero los montos
		for(int i = 0; i < 12; i++){
			montos[i] = new BigDecimal("0.00");
		}
		
		// Por movimiento se calcula el nuevo sueldo
		for(PadPlaneacionPersonalMovimiento movimiento : movimientos){
			double factorSueldo = movimiento.getIncremento() / (double)100;
			BigDecimal nuevoSueldo = movimiento.getSueldo().multiply(new BigDecimal(factorSueldo));
			// Se inicia desde el mes que aplica el movimiento el monto con el nuevo sueldo
			for(int i = movimiento.getMesMovimiento() - 1; i < 12; i++){
				montos[i] = montos[i].add(nuevoSueldo);
			}
		}
		
		MontosMensuales monto = new MontosMensuales();
		
		monto.setMontoEnero(montos[0]);
		monto.setMontoFebrero(montos[1]);
		monto.setMontoMarzo(montos[2]);
		monto.setMontoAbril(montos[3]);
		monto.setMontoMayo(montos[4]);
		monto.setMontoJunio(montos[5]);
		monto.setMontoJulio(montos[6]);
		monto.setMontoAgosto(montos[7]);
		monto.setMontoSeptiembre(montos[8]);
		monto.setMontoOctubre(montos[9]);
		monto.setMontoNoviembre(montos[10]);
		monto.setMontoDiciembre(montos[11]);
		
		return monto;
	}

	
	
}
